
#pragma once

#include "base/core/singleton.h"
#include "base/core/point3.h"

#include <vector>
#include <unordered_map>
#include <string>
#include "Common/ComTypeDefine.h"


class TeleporterLocation
{
public:
	TeleporterLocation()
	{
		m_id = 0;
	}

	TeleporterLocation(const TeleporterLocation& loc)
	{
		m_id = loc.m_id;
		m_mapid = loc.m_mapid;
		m_pos = loc.m_pos;
		m_transPos = loc.m_transPos;
	}

	uint32_t m_id;
	uint32_t m_mapid;
	Point3<float> m_pos; //传送点本身位置
	Point3<float> m_transPos; //传送点传送落地位置

};

class BornRefLocation
{
public:
	BornRefLocation() :m_nBornId(0), m_pos(0.0f, 0.0f, 0.0f){}
	~BornRefLocation(){}
	
	uint32_t m_nBornId;	//出生点ID
	Point3<float> m_pos; //出生点位置
};

//路径
class PathRefLocation
{
public:
	PathRefLocation() :m_mapId(0),m_id(0) { }
	~PathRefLocation() { }
public:
	uint32_t m_mapId;
	uint32_t m_id;
	std::vector<Point3<float> > m_vecPos;
};

//区域
class AreaRefLocation
{
public:
	AreaRefLocation() :m_nAreaId(0), m_radius(0.0f){ m_vecPos.clear(); }
	~AreaRefLocation(){}
	const Point3<float> *flagPos() const
	{
		const Point3<float> *ppos = nullptr;
		if (m_vecPos.size() >= 1)
		{
			ppos = &m_vecPos.at(0);
		}
		/*if (5 == m_vecPos.size()) //四边形,目前只有四边形会有标志位置
		{
			ppos = &m_vecPos.at(0);
		}*/
		return ppos;
	}

	uint32_t m_nAreaId;	//区域ID
	float    m_radius;	//半径（根据区域形状来的，具体的区域形状在 area.xlsx配置中有定义）
	VecPoint3 m_vecPos; //坐标（坐标个数根据区域形状来定义的）
};

//采集（草药，矿石，鱼）
class CollectRefLocation
{
public:
	CollectRefLocation() :m_collectId(0){ m_vecPos.clear(); }
	~CollectRefLocation(){}

	uint32_t m_collectId; //采集ID
	VecPoint3 m_vecPos; ///出生点坐标
};


//阻挡
class BlockRefLocation
{
public:
	BlockRefLocation() :m_blockId(0), m_pos(0.0,0.0,0.0){}
	~BlockRefLocation(){}

	uint32_t m_blockId; //阻挡ID
	Point3<float> m_pos; //出生点坐标
};


class CreatureRefLocation
{
public:
	CreatureRefLocation()
	{
		m_internalTime = 0;
		m_id = 0;
	}

	CreatureRefLocation(const CreatureRefLocation& loc)
	{
		m_bornPos = loc.m_bornPos;
		m_internalTime = loc.m_internalTime;
		m_id = loc.m_id;
	}
	

	Point3<float> m_bornPos; //monster出生点
	uint32_t m_id;
	uint64_t m_internalTime; //刷新间隔时间
};

class MonsterRefLocation : public CreatureRefLocation
{
public:
	MonsterRefLocation() :CreatureRefLocation()
	{
		m_deadTime = 0;
		m_fresh = 0;
		m_group = 0;
		m_RefLocIndex = 0;
	}
	MonsterRefLocation(const MonsterRefLocation& ref) :CreatureRefLocation(ref)
	{
		m_deadTime = ref.m_deadTime;
		m_group = ref.m_group;
		m_fresh = ref.m_fresh;
		m_RefLocIndex = ref.m_RefLocIndex;
		m_dir = ref.m_dir;
	}

	uint32_t m_RefLocIndex; //怪物数组中的索引 从0开始，默认为-1
	uint32_t m_group;		//编队ID
	uint32_t m_fresh;		//是否一开始就创建
	uint64_t m_deadTime;	
	Point3<float> m_scale;	//缩放比
	Point3<float> m_dir;
};

class NPCRefLocation : public CreatureRefLocation
{
public:
	NPCRefLocation() :CreatureRefLocation()
	{
		m_deadTime = 0;
		m_RefLocIndex = 0;
	}
	NPCRefLocation(const NPCRefLocation& ref) :CreatureRefLocation(ref)
	{
		m_deadTime = ref.m_deadTime;
		m_RefLocIndex = ref.m_RefLocIndex;
	}

	uint64_t m_deadTime;
	int32_t m_RefLocIndex; //NPC数组中的索引,从0开始，默认为-1
};

class MapLoactionCfg : public ManualSingleton < MapLoactionCfg >
{
	friend class ManualSingleton < MapLoactionCfg >;
public:
	typedef std::map < uint32_t, std::vector<MonsterRefLocation> > MonsterRefLocationMap;
	typedef std::unordered_map<uint32_t, std::vector<NPCRefLocation> > NPCRefLocationMap;


	typedef std::unordered_map<uint32_t, std::vector<BornRefLocation> > BornRefLocationMap;
	typedef std::unordered_map<uint32_t, std::unordered_map<uint32_t,AreaRefLocation> > AreaRefLocationMap;
	typedef std::unordered_map<uint32_t, TeleporterLocation> teleporterLocationMap;
	typedef std::unordered_map<uint32_t, MonsterRefLocationMap> monsterGroupRefMap;
	typedef std::unordered_map<uint32_t, PathRefLocation> PathLocationMap;
	typedef std::unordered_map<uint32_t, CollectRefLocation> collectLocationMap;
	typedef std::unordered_map<uint32_t, BlockRefLocation> blockLocationMap;
public:
	MapLoactionCfg();
	virtual ~MapLoactionCfg();
public:
	bool Init();
	bool LoadConfig(const std::string& cfgFile);
	bool UnInit();
public:

	bool isExistMapId(uint32_t mapId);
	MonsterRefLocationMap* getMonsterRefMap(uint32_t mapId);
	const vector<MonsterRefLocation> *GetMonsterRef(uint32_t mapId,uint32_t monsterId);
	const MonsterRefLocationMap *getMonsRefMap(uint32_t mapId);
	const MonsterRefLocation* GetRndomMonsterRef(uint32_t mapId, uint32_t monsterId);
	std::vector<NPCRefLocation>* getNPCRefLoc(uint32_t mapId);
	TeleporterLocation* getTeleporterLocation(uint32_t teleporterId);
	void getAllTeleporterId(std::vector<uint32_t>& vecId);
	Point3<float>  GetFirstTeleportPos(uint32_t mapID);
	uint32_t GetMapGroupMonsterCount(uint32_t mapId, uint32_t groupId, uint32_t monsterId);
	const std::vector<MonsterRefLocation>* GetMapGroupMonster(uint32_t mapId, uint32_t groupId);
	const BornRefLocation *RandBornLocation(uint32_t mapId);
	int32_t GetBornLocationCount(uint32_t mapId);
	const BornRefLocation *GetBornLocationByIdx(uint32_t mapId, int32_t idx);
	const std::vector<BornRefLocation> *GetMapBornLocation(uint32_t mapId);
	const BornRefLocation *GetMapBornLocation(uint32_t mapId, uint32_t bornId);
	const AreaRefLocation* GetAreaRefLoc(uint32_t mapId,uint32_t nAreaId);
	const CollectRefLocation *GetCollectRefLoc(uint32_t collectId);

	const PathRefLocation* GetPathRefLoc(uint32_t pathId);
	Point3<float> RandPosInArea(uint32_t areaId);
	bool InArea(uint32_t areaId, Point3<float> pos);
	Point3<float> GetNearRelivePos(uint32_t mapid,Point3<float> & currentPos,uint32_t cmap);  //找最近的复活点
	void GetAreaIdByMap(uint32_t mapid, std::vector<uint32_t> &vID);  //获取该地图的所有区域ID
	void GetSafeAreaIdByMap(uint32_t mapid, int32_t safeType, std::vector<uint32_t> &vID);//获取该地图的所有安全区域ID
	const BlockRefLocation *GetBlockRefLoc(uint32_t blockId); //获取阻挡信息
protected:
	NPCRefLocationMap m_npcRefLoc;
	BornRefLocationMap m_bornRefLoc;
	teleporterLocationMap m_teleporterLoc;
	monsterGroupRefMap m_monsterGroupRefMap;
	AreaRefLocationMap m_areaRefLoc;
	collectLocationMap m_collectLoc;
	PathLocationMap m_pathLoc;
	monsterGroupRefMap m_monsterRefMap;
	blockLocationMap m_blockRefMap;
};

#define g_MakeMapLocationCfg() (MapLoactionCfg::Instance())
#define g_GetMapLocationCfg() (MapLoactionCfg::GetInstance())
#define g_DelMapLocationCfg() (MapLoactionCfg::Destroy())
